/* 
 * Copyright (c) 2012, Fromentin Xavier, Schnell Michaël, Dervin Cyrielle, Brabant Quentin
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *      * The names of its contributors may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Fromentin Xavier, Schnell Michaël, Dervin Cyrielle OR Brabant Quentin 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package kameleon.gui.view;

import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import kameleon.exception.FileReadingException;
import kameleon.exception.KameleonException;
import kameleon.gui.exception.UnknownKeyException;
import kameleon.gui.language.SwitchLanguage;
import kameleon.gui.model.FileModel;
import kameleon.gui.model.Model;
import kameleon.gui.model.Observer;
import kameleon.gui.util.FileConstants;
import kameleon.gui.util.ImageUtility;
import kameleon.gui.util.LanguageConstants;

/**
 * View showing the currently selected file as well as the last time the
 * current file was used to generate others and the currently used charset.
 * 
 * @author		Fromentin Xavier, Schnell Michaël, Dervin Cyrielle
 * @version		1.0
 */
public class SelectionView extends JPanel 
implements Observer, FileConstants, LanguageConstants {

	/**
	 * Needed to serialize this class.
	 * 
	 * @see		java.io.Serializable
	 */
	private static final long serialVersionUID = 6674276013071380986L ;
	
	/**
	 * Constant used to initialize graphical components.
	 */
	private static final String EMPTY_TEXT = "" ;//$NON-NLS-1$
	
	/**
	 * Font used by plain text.
	 */
	private final Font PLAIN = new Font(
			this.getFont().getName(), Font.PLAIN, this.getFont().getSize()) ;
	
	/**
	 * Font used by italic text.
	 */
	private final Font ITALIC = new Font(
			this.getFont().getName(), Font.ITALIC, this.getFont().getSize()) ;
	
	/**
	 * Font used by bold text.
	 */
	private final Font BOLD = new Font(
			this.getFont().getName(), Font.BOLD, this.getFont().getSize()) ;
	
	/**
	 * Model of this view.
	 */
	protected Model model ;
	
	/**
	 * Label displaying the title for the file name.
	 */
	protected JLabel titleName ;
	
	/**
	 * Label displaying the the file name.
	 */
	protected JLabel fileName ;
	
	/**
	 * Label displaying the title of the last generation date.
	 */
	protected JLabel dateTitle ;
	
	/**
	 * Label displaying the last generation date.
	 */
	protected JLabel lastModificationDate ;
	
	/**
	 * Label displaying the title for the charset selection.
	 */
	protected JLabel encodingTitle ;
	
	/**
	 * Combo box used to specify the charset.
	 */
	protected JComboBox encodingList ;
	
	/**
	 * Button used to access detailed information about the last generation.
	 */
	protected JButton moreInfo ;
	
	/**
	 * JFrame containing this view.
	 */
	protected JFrame parent ;

	/**
	 * Sole constructor.
	 * 
	 * @param	model
	 * 			model of this view
	 * 
	 * @param	container
	 * 			parent frame of this instance
	 * 
	 * @throws	KameleonException
	 * 			if an error occurred while building this instance
	 */
	public SelectionView(JFrame container, Model model) throws KameleonException {
		super() ;
		this.parent = container;
		this.model = model ;
		this.model.addObserver(this) ;
		this.build() ;
	}// SelectionView(JFrame, Model)

	/**
	 * Builds the content of this view.
	 * 
	 * @throws 	UnknownKeyException 
	 * 			if a key for a displayed text could not be found
	 * 
	 * @throws 	FileReadingException
	 * 			If a format icon could not be loaded
	 */
	protected void build() throws UnknownKeyException, FileReadingException {
		GridBagLayout gridbag = new GridBagLayout() ;
		GridBagConstraints constraints ;
		this.setLayout(gridbag) ;
		this.setBorder(BorderFactory.createTitledBorder(EMPTY_TEXT)) ;

		// Name of the file (title)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = 1 ;
		constraints.weightx = 0.0 ;
		constraints.weighty = 0.0 ;
		constraints.insets = new Insets(0, 0, 5, 5) ;
		constraints.anchor = GridBagConstraints.BASELINE_TRAILING ;
		this.titleName = new JLabel(EMPTY_TEXT) ;
		this.titleName.setFont(this.BOLD) ;
		this.add(this.titleName) ;
		gridbag.setConstraints(this.titleName, constraints) ;
		
		// Name of the file (value)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = GridBagConstraints.REMAINDER ;
		constraints.weightx = 1.0 ;
		constraints.weighty = 0.0 ;
		constraints.anchor = GridBagConstraints.BASELINE_LEADING ;
		this.fileName = new JLabel(EMPTY_TEXT) ;
		this.fileName.setFont(this.ITALIC) ;
		this.add(this.fileName) ;
		gridbag.setConstraints(this.fileName, constraints) ;

		// Last generation date (title)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = 1 ;
		constraints.weightx = 0.0 ;
		constraints.weighty = 0.0 ;
		constraints.insets = new Insets(0, 0, 0, 5) ;
		constraints.anchor = GridBagConstraints.BASELINE_TRAILING ;
		this.dateTitle = new JLabel(EMPTY_TEXT) ;
		this.dateTitle.setFont(this.BOLD) ;
		this.add(this.dateTitle) ;
		gridbag.setConstraints(this.dateTitle, constraints) ;
		
		// Last generation date (value)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = GridBagConstraints.REMAINDER ;
		constraints.weightx = 1.0 ;
		constraints.weighty = 0.0 ;
		constraints.anchor = GridBagConstraints.BASELINE_LEADING ;
		constraints.weighty = 1.0 ;
		this.lastModificationDate = new JLabel(EMPTY_TEXT) ;
		this.lastModificationDate.setFont(this.ITALIC) ;
		this.add(this.lastModificationDate) ;
		gridbag.setConstraints(this.lastModificationDate, constraints) ;

		// Charset (title)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = 1 ;
		constraints.weightx = 0.0 ;
		constraints.weighty = 0.0 ;
		constraints.insets = new Insets(0, 0, 0, 5) ;
		constraints.anchor = GridBagConstraints.BASELINE_TRAILING ;
		this.encodingTitle = new JLabel(EMPTY_TEXT) ;
		this.encodingTitle.setFont(this.BOLD) ;
		this.add(this.encodingTitle) ;
		gridbag.setConstraints(this.encodingTitle, constraints) ;
		
		// Charset (value)
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = 1 ;
		constraints.anchor = GridBagConstraints.BASELINE_LEADING ;
		this.encodingList = new JComboBox(FileModel.getDefaultCharsets()) ;
		this.encodingList.setSelectedItem(this.model.getCharset()) ;
		this.encodingList.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				SelectionView.this.model.setCharset(
						(String) SelectionView.this.encodingList.getSelectedItem()) ;
			}// actionPerformed(ActionEvent)
		}) ;
		this.add(this.encodingList) ;
		gridbag.setConstraints(this.encodingList, constraints) ;

		// More information button
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = GridBagConstraints.REMAINDER ;
		constraints.weighty = 0.0 ;
		constraints.anchor = GridBagConstraints.NORTHEAST ;
		InputStream src = new BufferedInputStream(
				SelectionView.class.getResourceAsStream(MORE_INFORMATION_FILE)) ;
		ImageIcon buttonIcon = new ImageIcon(ImageUtility.getImageBytes(src)) ;
		try {
			src.close() ;
		} catch (IOException ioe) {
			throw new FileReadingException(new File(MORE_INFORMATION_FILE)) ;
		}// try
		this.moreInfo = new JButton(buttonIcon);
		this.moreInfo.setToolTipText(MORE_INFO_BUTTON);
		this.moreInfo.setEnabled(SelectionView.this.model.fileIsSelected() 
				&& (this.model.getSelectedFileInfo().getLastGeneration() != null)) ;
		this.moreInfo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e){
				try {
					new MoreInformationFrame(SelectionView.this.parent, 
							SelectionView.this.model).setVisible(true) ;
				} catch (KameleonException ke) {
					SelectionView.this.model.displayDebugInformation(ke) ;
				}// try
			}
		});
		this.add(this.moreInfo) ;
		gridbag.setConstraints(this.moreInfo, constraints) ;
		
		this.reloadLanguage() ;
	}// build

	/**
	 * Updates the displayed information about the currently selected file.
	 * 
	 * @throws 	UnknownKeyException
	 * 			if an error occurred while updating the text of this view
	 */
	@Override
	public void update() throws UnknownKeyException {
		SwitchLanguage sl = SwitchLanguage.getInstance() ;
		
		if (this.model.fileIsSelected()) {
			this.fileName.setText(this.model.getSelectedFileInfo().getName()) ;
			this.fileName.setFont(this.PLAIN) ;
			String last = this.model.getFileLastGenerationDate() ;
			if (last == null) {
				this.lastModificationDate.setText(sl.getText(NEVER_GENERATED));
			} else {
				this.lastModificationDate.setText(last) ;
			}// if
			this.lastModificationDate.setFont(this.PLAIN) ;
		} else {
			this.fileName.setText(sl.getText(NO_FILE)) ;
			this.fileName.setFont(this.ITALIC) ;
			this.lastModificationDate.setText(sl.getText(NO_FILE)) ;
			this.lastModificationDate.setFont(this.ITALIC) ;
		}// if
		
		this.moreInfo.setEnabled(SelectionView.this.model.fileIsSelected() 
				&& (this.model.getSelectedFileInfo().getLastGeneration() != null)) ;
	}// update()

	/**
	 * Updates the text to match the currently selected language.
	 * 
	 * @throws 	UnknownKeyException
	 * 			if an error occurred while updating the text of this view
	 */
	@Override
	public void reloadLanguage() throws UnknownKeyException {
		SwitchLanguage sl = SwitchLanguage.getInstance() ;
		
		this.setBorder(BorderFactory.createTitledBorder(
				sl.getText(SELECTION_TITLE_BORDER)));
		this.titleName.setText(sl.getText(NAME_LABEL)) ;
		this.dateTitle.setText(sl.getText(LAST_GENERATED)) ;
		this.encodingTitle.setText(sl.getText(CHARSET_SELECTION)) ;
		this.moreInfo.setToolTipText((sl.getText(MORE_INFO_BUTTON))) ;
		if (!this.model.fileIsSelected()) {
			this.lastModificationDate.setText(sl.getText(NO_FILE)) ;
			this.fileName.setText(sl.getText(NO_FILE)) ;
		} else {
			String last = this.model.getFileLastGenerationDate() ;
			if (last == null) {
				this.lastModificationDate.setText(sl.getText(NEVER_GENERATED)) ;
			} else {
				this.lastModificationDate.setText(last) ;
			}// if
		}// if
	}// reloadLanguage()

}// class SelectionView